package com.baseproject.datasource.local.database.dao;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.util.Log;

import com.baseproject.datasource.local.database.dao.annotation.DbField;
import com.baseproject.datasource.local.database.dao.annotation.DbTable;
import com.baseproject.util.LogUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by hp on 2017/3/9.
 */

public abstract class BaseDao<T> implements IBaseDao<T> {
    protected static final String TEXT_TYPE = " TEXT";
    protected static final String INTEGER_TYPE = " INTEGER";
    protected static final String BOOLEAN_TYPE = " BOOLEAN";
    protected static final String FLOAT_TYPE = " FLOAT";
    protected static final String COMMA_SEP = ",";


    private DatabaseHelper helper;

    /**
     * 具体的Class对象
     */
    private Class<T> entity;

    /**
     * 列名和javabean对象的成员变量名的映射map
     * 结构为列名--> 域
     */
    private HashMap<String, Field> cacheMap;

    boolean isInit;

    String tableName;

    /**
     * @param entity
     * @return 返回是否初始化成功
     */
    protected synchronized boolean init(Class<T> entity, DatabaseHelper helper) {
        if (!isInit) {
            this.entity = entity;
            this.helper = helper;
            //拿到表名
            if (entity.getAnnotation(DbTable.class) != null) {
                tableName = helper.getTableName(entity);
            }
            //建表逻辑现在放在databasehelper的onCreate里
            //开始实现映射关系
            initCacheMap();
            isInit = true;
        }
        return isInit;
    }

    private void initCacheMap() {
        SQLiteDatabase db = helper.getWritableDatabase();
        cacheMap = new HashMap<>();
        //查空表，得到表结构
        String sql = "select * from " + this.tableName + " limit 1,0";
        Cursor cursor = db.rawQuery(sql, null);
        //得到表的列名数组
        String[] columnNames = cursor.getColumnNames();
        //得到成员变量数组
        Field[] columnFields = entity.getFields();
        for (Field field : columnFields) {
            field.setAccessible(true);
        }
        for (String columnName : columnNames) {
            Field resultField = null;
            for (Field field : columnFields) {
                //找到列名与bean对象的成员变量的映射关系
                DbField anno = field.getAnnotation(DbField.class);
                if ((anno != null && columnName.equals(anno.value()))
                        || anno != null && columnName.equals(field.getName())) {
                    resultField = field;
                    break;
                }
            }
            if (null != resultField) {
                cacheMap.put(columnName, resultField);
            }
        }
        db.close();
    }

    @Override
    public Long insert(T entity) {
        SQLiteDatabase db = helper.getWritableDatabase();
        HashMap<String, String> map = getValues(entity);
        ContentValues contentValues = getContentValues(map);
        Long result = db.insert(tableName, null, contentValues);
        db.close();
        return result;
    }

    @Override
    public int delete(String where) {
        SQLiteDatabase db = helper.getWritableDatabase();
        int count = db.delete(tableName, where, null);
        db.close();
        return count;
    }

    @Override
    public Long update(T entity, String where) {
        return null;
    }

    @Override
    public List<T> query(String[] columns, String where) {
        SQLiteDatabase db = helper.getReadableDatabase();
        List<T> queryResult = new ArrayList<>();
        Cursor c = db.query(tableName, columns, where, null, null, null, null);
        if (c != null && c.getCount() > 0) {
            String[] cloumnNames = c.getColumnNames();
            while (c.moveToNext()) {
                try {
                    Object obj = entity.newInstance();
                    for (String colomnName : cloumnNames) {
                        Field field = cacheMap.get(colomnName);
                        if (field != null) {
                            // 可以直接对 private 的属性赋值
                            field.setAccessible(true);
                            switch (field.getType().getName()) {
                                case "int":
                                    Integer valueInt = c.getInt(c.getColumnIndexOrThrow(colomnName));
                                    field.set(obj, valueInt);
                                    break;
                                case "boolean":
                                    boolean valueBoolean = c.getInt(c.getColumnIndexOrThrow(colomnName)) > 0;
                                    field.set(obj, valueBoolean);
                                    break;
                                case "float":
                                    float valueFloat = c.getFloat(c.getColumnIndexOrThrow(colomnName));
                                    field.set(obj, valueFloat);
                                    break;
                                case "java.lang.Integer":
                                    int valueInteger = c.getInt(c.getColumnIndexOrThrow(colomnName));
                                    field.set(obj, valueInteger);
                                    break;
                                case "java.lang.String":
                                    String valueString = c.getString(c.getColumnIndexOrThrow(colomnName));
                                    field.set(obj, valueString);
                                    break;
                            }
                        }
                    }
                    queryResult.add((T) obj);
                } catch (InstantiationException e) {
                    LogUtils.e("getBaseDao Exception: " + Log.getStackTraceString(e));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        if (c != null) {
            c.close();
        }
        db.close();
        return queryResult;
    }

    private ContentValues getContentValues(Map<String, String> map) {
        ContentValues contentValues = new ContentValues();
        Set keys = map.keySet();
        Iterator iterator = keys.iterator();
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            String value = map.get(key);
            if (value != null) {
                contentValues.put(key, value);
            }
        }
        return contentValues;
    }

    /**
     * 把User对象解析成HashMap
     * tb_name --> "张三"
     * t User
     *
     * @return
     */
    private HashMap<String, String> getValues(T t) {
        HashMap<String, String> resultMap = new HashMap<>();
        Iterator<Field> fieldIterator = cacheMap.values().iterator();
        while (fieldIterator.hasNext()) {
            Field field = fieldIterator.next();

            String cacheKey = field.getAnnotation(DbField.class).value();
            if (TextUtils.isEmpty(cacheKey)) {
                cacheKey = field.getName();//所需要的表字段名就是域名
            }
            String cacheValue = null;

            try {
                if (field.get(t) == null) {
                    continue;
                }
                cacheValue = field.get(t).toString();
            } catch (Exception e) {

            }
            resultMap.put(cacheKey, cacheValue);
        }
        return resultMap;
    }

}
